#include "loginview.h"
#include "actionmanager.h"
#include "libs/controls/toastlabel.h"
#include "libs/core/user/localuser.h"
#include "ui_loginview.h"
#include "usersettings.h"
#include "utils/logintask.h"
#include "yingce.h"
#include <QCryptographicHash>
#include <QRegularExpression>
#include <QRegularExpressionValidator>
#include <QShortcut>

LoginView::LoginView(QWidget* parent) : QFrame(parent), ui(new Ui::LoginView)
{
    ui->setupUi(this);
    ui->name_edit->setMaxLength(32);
    ui->password_edit->setMaxLength(32);
    ui->password_edit->setEchoMode(QLineEdit::Password);
    ui->code_edit->setMaxLength(6);
    ui->code_label->hide();
    ui->code_edit->hide();
    ui->correct_code_label->hide();
    ui->login_button->setEnabled(false);
    ui->login_button->setDefault(true);
    ui->register_button->setProperty("type", "link");
    ui->name_edit->setValidator(
            new QRegularExpressionValidator(QRegularExpression("^[a-zA-Z][a-zA-Z0-9_@-]*$"), this));
    if (UserSettings::instance().loginUser().name().isEmpty()) {
        ui->name_edit->setFocus();
    } else {
        ui->name_edit->setText(UserSettings::instance().loginUser().name());
        ui->password_edit->setFocus();
    }
    ui->auto_login_checkbox->setChecked(UserSettings::instance().loginUser().autoLogin());
    setTabOrder({ ui->name_edit, ui->password_edit, ui->login_button, ui->cancel_button,
                  ui->register_button });
    updateButtonStatus();

    new QShortcut(
            QKeySequence("ALT+CTRL+SHIFT+R"), this, this,
            [this] {
                const bool enabled = !ui->register_button->isVisibleTo(this);
                ui->register_button->setVisible(enabled);
                ActionManager::instance()->registerAccountAction()->setEnabled(enabled);
            },
            Qt::WindowShortcut);

    // // 自动登录
    // if (UserSettings::instance().loginUser().autoLogin()
    //     && UserSettings::instance().loginUser().isValid()) {
    //     LoginTask* lt = new LoginTask(UserSettings::instance().loginUser(), this);
    //     connect(lt, &LoginTask::finished, this, &LoginView::finished);
    //     connect(lt, &LoginTask::failed, this, [this](int error, const QString& msg) {
    //         Q_UNUSED(error)
    //         sender()->deleteLater();
    //         updateUiStatus(false);
    //         yc::ToastLabel::showMessage(tr("Failed to login, the error is \"%1\".").arg(msg),
    //         this);
    //     });
    //     updateUiStatus(true);
    //     lt->start();
    // }

    connect(ui->name_edit, &QLineEdit::textChanged, this, &LoginView::updateButtonStatus);
    connect(ui->password_edit, &QLineEdit::textChanged, this, &LoginView::updateButtonStatus);
    connect(ui->password_edit, &QLineEdit::returnPressed, ui->login_button, &QPushButton::click);
    connect(ui->login_button, &QPushButton::clicked, this, [this] {
        updateUiStatus(true);
        const QString name = ui->name_edit->text().trimmed();
        const QString code = ui->code_edit->text().trimmed();
        const QString pwd = ui->password_edit->text().trimmed();
        const QString md5pwd = QString::fromUtf8(
                QCryptographicHash::hash(pwd.toUtf8(), QCryptographicHash::Md5).toBase64());
        login(name, md5pwd, code);
    });
    connect(ui->register_button, &QPushButton::clicked, this, &LoginView::registerRequested);
    connect(ui->cancel_button, &QPushButton::clicked, this, &LoginView::cancelRequested);
    connect(ui->auto_login_checkbox, &QCheckBox::clicked, this,
            [](bool checked) { UserSettings::instance().loginUser().setAutoLogin(checked); });

    connect(YingCe::instance()->localUser(), &yc::LocalUser::loginStatusChanged, this,
            [this](int status) { updateUiStatus(status == yc::LocalUser::LOGINING_STATUS); });
}

void LoginView::setName(const QString& name)
{
    if (!name.isEmpty()) {
        ui->name_edit->setText(name);
    }
}

void LoginView::updateUiStatus(bool busy)
{
    ui->name_edit->setReadOnly(busy);
    ui->password_edit->setReadOnly(busy);
    ui->login_button->setEnabled(!busy);
    ui->register_button->setEnabled(!busy);
}

void LoginView::updateButtonStatus()
{
    const QString name = ui->name_edit->text().trimmed();
    const QString pwd = ui->password_edit->text().trimmed();
    const QString code = ui->code_edit->text().trimmed();
    ui->login_button->setEnabled(
            !name.isEmpty() && !pwd.isEmpty()
            && code.compare(ui->correct_code_label->text(), Qt::CaseInsensitive) == 0);
}

void LoginView::login(const QString& name, const QString& pwd, const QString& code)
{
    LoginTask* t = new LoginTask(name, pwd, code, this);
    connect(t, &LoginTask::finished, this, &LoginView::finished);
    connect(t, &LoginTask::failed, this, [this](int error, const QString& msg) {
        Q_UNUSED(error)
        LoginTask* p = qobject_cast<LoginTask*>(sender());
        if (!p->code().isEmpty()) {
            if (!ui->code_label->isVisibleTo(this)) {
                ui->code_label->show();
                ui->code_edit->show();
                ui->correct_code_label->show();
            }
            ui->correct_code_label->setText(p->code());
        }
        updateUiStatus(false);
        yc::ToastLabel::showMessage(msg, this);
    });
    t->start();
}
